class Connection;
// DISCONCTED -- 连接关闭状态发  CONNECTING -- 连接建立成功 - 待处理状态
// CONNECTED -- 连接建立完成吗,设置完毕,可通信   DISCONNECTING  -- 待关闭

typedef enum { DISCONECTED, CONNECTING, CONNECTED, DISCONNECTING } ConnStatu;
using PtrConnection = std::shared_ptr<Connection>;

class Connection : public std::enable_shared_from_this<Connection> {
private:
    uint64_t _conn_id; //连接的id,
    int _sockfd;       //连接关联的描述符
    bool _enable_inactive_release;  //连接是否启动非活跃销毁的判断标志
    EventLoop *_loop; //连接关联的Eventloop
    ConnStatu _statu; //连接状态
    Socket _socket;  //套接字操作管理
    Channel _channel; //连接的事件管理
    Buffer _in_buffer; //输入缓存区
    Any _context; //请求的接受处理上下文
    
    using ConnectedCallback = std::function<void(const PtrConnection&)>;
    using MessageCallback = std::function<void(const PtrConnection&, Buffer*)>;
    using CloseCallback = std::function<void(const PtrConnection&)>;
    using AnyEventCallback = std::function<void(const PtrConnection&)>;
    ConnectedCallback _connected_callback;
    MessageCallback _message_callback;
    CloseCallback _closed_callback;
    AnyEventCallback _event_callback;
    //服务器移除信息。
    CloseCallback _server_closed_callback;
private:
    void HandleRead() {
        char buf[65536];
        ssize_t ret = _socket.NonBlockRecv(buf, 65535);
        if (ret < 0) {
            //出错
            return ShutdownInLoop();
        }
        _in_buffer.WriteAndPush(buf, ret);
        if (_in_buffer.ReadAbleSize() > 0) {
            return _message_callback(shared_from_this(), &_in_buffer);
        }
    }
    
    void HandleWrite() {
        // _out_buffer 中保存的数据就是要发送的数据
        ssize_t ret = _socket.NonBlockSend(_out_buffer.ReadPosition(), _out_buffer.ReadAbleSize());
        if (ret < 0) {
            //关闭连接
            if (_in_buffer.ReadAbleSize() > 0) {
                _message_callback(shared_from_this(), &_in_buffer);
            }
            return Release();
        }
        _out_buffer.MoveReadOffset(ret);
        if (_out_buffer.ReadAbleSize() == 0) {
            _channel.DisableWrite();
            if (_statu == DISCONNECTING) {
                return Release();
            }
        }
        return;
    }

    void HandleClose() {
        if (_in_buffer.ReadAbleSize() > 0) {
            _message_callback(shared_from_this(), &_in_buffer);
        }
        return Release();
    }
    
    void HandleError() {
        return HandleClose();
    }

    void HandleEvent() {
        if (_event_inactive_release == true) {
            _loop->TimerRefresh(_conn_id);  
        }
        if(_event_callback) _event_callback(shared_from_this());
    }
    
    void EstablishedInLoop() {
        assert(_statu == CONNECTING);
        _statu = CONNECTED; 
        //启动读监控
        _channe.EnableRead();
        if(_connected_callback) _connected_callback(shared_from_this());
    }
    
    void ReleaseInLoop() {
        _statu = DISCONECTED;
        _channel.Remove();
        _soket.Close();
        if(_loop->HasTimer(_conn_id)){
            CancelInactiveRelease();
        }
        if(_closed_callback) _colsed_callback(shared_from_this());
        if(_server_closed_callback) _server_closed_callback(shared_from_this());
    }
    
    void SendInLoop(Buffer &&buf) {
        if (_statu == DISCONNECTED) {
            return;
        }
        _out_buffer.writeBufferAndPush(buf);
        if(_channel.WriteAble()==false){
            _channel.EnableWrite();
        }
    }    

    //关闭操作，之前需判端还有无数据待处理
    void ShutdownInLoop(){
        _statu = DISCONNECTING;
        if(_in_buffer.ReadAbleSize()>0){
            if(_message_callback){
                _message_callback(shared_from_this(),&_in_buffer);
            }
        }
        if(_in_buffer.ReadAbleSize()>0){
            if(_channel.WriteAble() == false){
                _channel.EnableWrite();
            }
        }
        if(_out_buffer.ReadAbleSize() == 0){
            Release();
        }
    }

    void EnableInactiveReleaseInLoop() {
        _enable_inactive_release = true;
        if(_loop->HashTimer(_conn_id)){
            return _loop->TimerRefresh(_conn_id);
        }
        _loop->TimerAdd(_conn_id,sec,std::bind(&Connection::ReleaseInLoop,this));
    }

    void CancelInactiveReleaseInLoop() {
        _enable_inactive_release = false;
        if( _loop->HashTimer(_conn_id)){
            _loop->TimerCancel(_conn_id);
        }
    }

    void UpgradeInLoop(const Any &context,
    const ConnectedCallback &conn,
    const MessageCallback &msg,
    const CloseCallback &closed,
    const AnyEventCallback &event){
        _context = context;
        _connected_callback = conn;
        _message_callback = msg;
        _closed_callback = closed;
        _event_callback = event;
    }
    
public:
    Connection(EventLoop *loop, uint64_t conn_id, int sockfd)
    : _conn_id(conn_id), _sockfd(sockfd), _enable_inactive_release(false), 
    _loop(loop), _statu(CONNECTED), _socket(_sockfd), _channel(loop, _sockfd) {
        _channel.SetCloseCallback(std::bind(&Connection::HandleClose, this));
        _channel.SetEventCallback(std::bind(&Connection::HandleRead, this));
        _channel.SetReadCallback(std::bind(&Connection::HandleWrite, this));
        _channel.SetWriteCallback(std::bind(&Connection::HandleWrite, this));
        _channel.SetErrorCallback(std::bind(&Connection::HandleError, this));
    }
    
    ~Connection() { lg("Info", "RELEASE CONNECTION:%p", this); }
    
    int Fd() { return _sockfd; }

    int Id() { return _conn_id; }
    
    bool Connection() { return (_statu == CONNECTED); }

    void SetContext(const Any &context) { _context = context; }

    Any *GetContext() { return &_context; }
    
    void SetConnectedCallback(const ConnectedCallback &cb) {
        _connected_callback = cb;
    }
    
    void Established() {
        _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop, this));
    }

    void Send(const char *data, size_t len) {
        Buffer buf;
        buf.WriteAndPush(data, len);
        _loop->RunInLoop(std::bind(&Connection::SendInLoop, this, std::move(buf)));
    }
    
    void Shutdown() {
        _loop->RunInLoop(std::bind(&Connection::ShutdownInLoop, this));
    }
    
    void Release() {
        _loop->QueueInLoop(std::bind(&Connection::ReleaseInLoop, this));
    }
    // 取消非活跃连接
    void EnableInactiveRelease(int sec) {
        _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop, this,sec));
    }
    //取消非活跃连接
    void CancelInactiveRelease() {
        _loop->RunInLoop(std::bind(&Connection::CancelInactiveReleaseInLoop, this));
    }
    //切换协议--重置上下文以及阶段性回调处理函数 -- 而是这个接口必须要在EventLoop线程中立即执行
    //防备新的事件触发后,处理的时候,切换的任务还没有被执行-会导致数据使用原协议处理了。
    void Upgrade(const Any &context, const ConnectedCallback &conn, const MessageCallback &msg,
        const CloseCallback &closed, const AnyEventCallback &event) {
        _loop->AssertInLoop();
        _loop->RunInLoop(std::bind(&Connection::UpgradeInLoop, this, context, conn, msg, closed, event));
    }
};


